<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="pandoc" />

<meta name="viewport" content="width=device-width, initial-scale=1">

<meta name="author" content="Baptiste Auguié" />

<meta name="date" content="2019-07-13" />

<title>Laying out multiple plots on a page</title>



<style type="text/css">code{white-space: pre;}</style>
<style type="text/css" data-origin="pandoc">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; position: absolute; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
  { position: relative; }
pre.numberSource a.sourceLine:empty
  { position: absolute; }
pre.numberSource a.sourceLine::before
  { content: attr(data-line-number);
    position: absolute; left: -5em; text-align: right; vertical-align: baseline;
    border: none; pointer-events: all;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
    color: #aaaaaa;
  }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
div.sourceCode
  {  }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */

</style>
<script>
// apply pandoc div.sourceCode style to pre.sourceCode instead
(function() {
  var sheets = document.styleSheets;
  for (var i = 0; i < sheets.length; i++) {
    if (sheets[i].ownerNode.dataset["origin"] !== "pandoc") continue;
    try { var rules = sheets[i].cssRules; } catch (e) { continue; }
    for (var j = 0; j < rules.length; j++) {
      var rule = rules[j];
      // check if there is a div.sourceCode rule
      if (rule.type !== rule.STYLE_RULE || rule.selectorText !== "div.sourceCode") continue;
      var style = rule.style.cssText;
      // check if color or background-color is set
      if (rule.style.color === '' || rule.style.backgroundColor === '') continue;
      // replace div.sourceCode by a pre.sourceCode rule
      sheets[i].deleteRule(j);
      sheets[i].insertRule('pre.sourceCode{' + style + '}', j);
    }
  }
})();
</script>



<style type="text/css">body {
background-color: #fff;
margin: 1em auto;
max-width: 700px;
overflow: visible;
padding-left: 2em;
padding-right: 2em;
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.35;
}
#header {
text-align: center;
}
#TOC {
clear: both;
margin: 0 0 10px 10px;
padding: 4px;
width: 400px;
border: 1px solid #CCCCCC;
border-radius: 5px;
background-color: #f6f6f6;
font-size: 13px;
line-height: 1.3;
}
#TOC .toctitle {
font-weight: bold;
font-size: 15px;
margin-left: 5px;
}
#TOC ul {
padding-left: 40px;
margin-left: -1.5em;
margin-top: 5px;
margin-bottom: 5px;
}
#TOC ul ul {
margin-left: -2em;
}
#TOC li {
line-height: 16px;
}
table {
margin: 1em auto;
border-width: 1px;
border-color: #DDDDDD;
border-style: outset;
border-collapse: collapse;
}
table th {
border-width: 2px;
padding: 5px;
border-style: inset;
}
table td {
border-width: 1px;
border-style: inset;
line-height: 18px;
padding: 5px 5px;
}
table, table th, table td {
border-left-style: none;
border-right-style: none;
}
table thead, table tr.even {
background-color: #f7f7f7;
}
p {
margin: 0.5em 0;
}
blockquote {
background-color: #f6f6f6;
padding: 0.25em 0.75em;
}
hr {
border-style: solid;
border: none;
border-top: 1px solid #777;
margin: 28px 0;
}
dl {
margin-left: 0;
}
dl dd {
margin-bottom: 13px;
margin-left: 13px;
}
dl dt {
font-weight: bold;
}
ul {
margin-top: 0;
}
ul li {
list-style: circle outside;
}
ul ul {
margin-bottom: 0;
}
pre, code {
background-color: #f7f7f7;
border-radius: 3px;
color: #333;
white-space: pre-wrap; 
}
pre {
border-radius: 3px;
margin: 5px 0px 10px 0px;
padding: 10px;
}
pre:not([class]) {
background-color: #f7f7f7;
}
code {
font-family: Consolas, Monaco, 'Courier New', monospace;
font-size: 85%;
}
p > code, li > code {
padding: 2px 0px;
}
div.figure {
text-align: center;
}
img {
background-color: #FFFFFF;
padding: 2px;
border: 1px solid #DDDDDD;
border-radius: 3px;
border: 1px solid #CCCCCC;
margin: 0 5px;
}
h1 {
margin-top: 0;
font-size: 35px;
line-height: 40px;
}
h2 {
border-bottom: 4px solid #f7f7f7;
padding-top: 10px;
padding-bottom: 2px;
font-size: 145%;
}
h3 {
border-bottom: 2px solid #f7f7f7;
padding-top: 10px;
font-size: 120%;
}
h4 {
border-bottom: 1px solid #f7f7f7;
margin-left: 8px;
font-size: 105%;
}
h5, h6 {
border-bottom: 1px solid #ccc;
font-size: 105%;
}
a {
color: #0033dd;
text-decoration: none;
}
a:hover {
color: #6666ff; }
a:visited {
color: #800080; }
a:visited:hover {
color: #BB00BB; }
a[href^="http:"] {
text-decoration: underline; }
a[href^="https:"] {
text-decoration: underline; }

code > span.kw { color: #555; font-weight: bold; } 
code > span.dt { color: #902000; } 
code > span.dv { color: #40a070; } 
code > span.bn { color: #d14; } 
code > span.fl { color: #d14; } 
code > span.ch { color: #d14; } 
code > span.st { color: #d14; } 
code > span.co { color: #888888; font-style: italic; } 
code > span.ot { color: #007020; } 
code > span.al { color: #ff0000; font-weight: bold; } 
code > span.fu { color: #900; font-weight: bold; }  code > span.er { color: #a61717; background-color: #e3d2d2; } 
</style>




</head>

<body>




<h1 class="title toc-ignore">Laying out multiple plots on a page</h1>
<h4 class="author">Baptiste Auguié</h4>
<h4 class="date">2019-07-13</h4>



<p>An individual ggplot object contains multiple pieces – axes, plot panel(s), titles, legends –, and their layout is defined and enforced via the <code>gtable</code> package, itself built around the lower-level <code>grid</code> package. Plots themselves become <em>graphical objects</em>, which can be arranged on a page using e.g. the <code>gridExtra</code> or <code>egg</code> packages, which provide helper functions for such multi-object layouts. The following schematic illustrates the main relations between these packages.</p>
<div class="figure">
<img src="" alt="Schematic illustration of the links between packages ggplot2, gtable, grid, egg and gridExtra." />
<p class="caption">Schematic illustration of the links between packages <code>ggplot2</code>, <code>gtable</code>, <code>grid</code>, <code>egg</code> and <code>gridExtra</code>.</p>
</div>
<div id="arranging-multiple-plots-on-a-page" class="section level2">
<h2>Arranging multiple plots on a page</h2>
<p>To begin, we’ll create four example plots that we can experiment with.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="kw">library</span>(ggplot2)</a>
<a class="sourceLine" id="cb1-2" data-line-number="2">p1 &lt;-<span class="st"> </span><span class="kw">qplot</span>(mpg, wt, <span class="dt">data =</span> mtcars, <span class="dt">colour =</span> cyl)</a>
<a class="sourceLine" id="cb1-3" data-line-number="3">p2 &lt;-<span class="st"> </span><span class="kw">qplot</span>(mpg, <span class="dt">data =</span> mtcars) <span class="op">+</span><span class="st"> </span><span class="kw">ggtitle</span>(<span class="st">&quot;title&quot;</span>)</a>
<a class="sourceLine" id="cb1-4" data-line-number="4">p3 &lt;-<span class="st"> </span><span class="kw">qplot</span>(mpg, <span class="dt">data =</span> mtcars, <span class="dt">geom =</span> <span class="st">&quot;dotplot&quot;</span>)</a>
<a class="sourceLine" id="cb1-5" data-line-number="5">p4 &lt;-</a>
<a class="sourceLine" id="cb1-6" data-line-number="6"><span class="st">  </span>p1 <span class="op">+</span><span class="st"> </span><span class="kw">facet_wrap</span>( <span class="op">~</span><span class="st"> </span>carb, <span class="dt">nrow =</span> <span class="dv">1</span>) <span class="op">+</span><span class="st"> </span><span class="kw">theme</span>(<span class="dt">legend.position =</span> <span class="st">&quot;none&quot;</span>) <span class="op">+</span></a>
<a class="sourceLine" id="cb1-7" data-line-number="7"><span class="st">  </span><span class="kw">ggtitle</span>(<span class="st">&quot;facetted plot&quot;</span>)</a></code></pre></div>
<div class="figure">
<img src="" alt="A few plots that we want to organise on a page." />
<p class="caption">A few plots that we want to organise on a page.</p>
</div>
<div id="basic-strategy" class="section level3">
<h3>Basic strategy</h3>
<p>The easiest approach to assemble multiple plots on a page is to use the <code>grid.arrange()</code> function from the <code>gridExtra</code> package; in fact, that’s what we used for the previous figure. With <code>grid.arrange()</code>, one can reproduce the behaviour of the base functions <code>par(mfrow=c(r,c))</code>, specifying either the number of rows or columns,</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb2-1" data-line-number="1"><span class="kw">grid.arrange</span>(p1, p2, <span class="dt">nrow =</span> <span class="dv">1</span>)</a></code></pre></div>
<div class="figure">
<img src="" alt="Basic usage of grid.arrange()" />
<p class="caption">Basic usage of <code>grid.arrange()</code></p>
</div>
<p>If layout parameters are ommitted altogether, <code>grid.arrange()</code> will calculate a default number of rows and columns to organise the plots.</p>
<p>More complex layouts can be achieved by passing specific dimensions (widths or heights), or a layout matrix defining the position of each plot in a rectangular grid. For the sake of clarity, we’ll use a list <code>gl</code> of dummy rectangles, but the process is identical for plots.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="kw">grid.arrange</span>(</a>
<a class="sourceLine" id="cb3-2" data-line-number="2">  <span class="dt">grobs =</span> gl,</a>
<a class="sourceLine" id="cb3-3" data-line-number="3">  <span class="dt">widths =</span> <span class="kw">c</span>(<span class="dv">2</span>, <span class="dv">1</span>, <span class="dv">1</span>),</a>
<a class="sourceLine" id="cb3-4" data-line-number="4">  <span class="dt">layout_matrix =</span> <span class="kw">rbind</span>(<span class="kw">c</span>(<span class="dv">1</span>, <span class="dv">2</span>, <span class="ot">NA</span>),</a>
<a class="sourceLine" id="cb3-5" data-line-number="5">                        <span class="kw">c</span>(<span class="dv">3</span>, <span class="dv">3</span>, <span class="dv">4</span>))</a>
<a class="sourceLine" id="cb3-6" data-line-number="6">)</a></code></pre></div>
<div class="figure">
<img src="" alt="Illustrating further arguments of grid.arrange(), namely layout_matrix and relative widths." />
<p class="caption">Illustrating further arguments of <code>grid.arrange()</code>, namely <code>layout_matrix</code> and relative widths.</p>
</div>
<p>Further examples are available in a dedicated <code>gridExtra</code> <a href="https://CRAN.R-project.org/package=gridExtra/vignettes/arrangeGrob.html">vignette</a>.</p>
</div>
<div id="plot-insets" class="section level3">
<h3>Plot insets</h3>
<p>A special case of layouts is where one of the plots is to be placed within another, typically as an inset of the plot panel. In this case, <code>grid.arrange()</code> cannot help, as it only provides rectangular layouts with non-overlapping cells. Instead, a simple solution is to convert the plot into a <em>grob</em>, and place it using <code>annotation_custom()</code> within the plot panel. Note the related <code>geom_custom()</code> function, suitable when different facets should display different annotations.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb4-1" data-line-number="1">g &lt;-<span class="st"> </span><span class="kw">ggplotGrob</span>(<span class="kw">qplot</span>(<span class="dv">1</span>, <span class="dv">1</span>) <span class="op">+</span></a>
<a class="sourceLine" id="cb4-2" data-line-number="2"><span class="st">                  </span><span class="kw">theme</span>(<span class="dt">plot.background =</span> <span class="kw">element_rect</span>(<span class="dt">colour =</span> <span class="st">&quot;black&quot;</span>)))</a>
<a class="sourceLine" id="cb4-3" data-line-number="3"><span class="kw">qplot</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">10</span>, <span class="dv">1</span><span class="op">:</span><span class="dv">10</span>) <span class="op">+</span></a>
<a class="sourceLine" id="cb4-4" data-line-number="4"><span class="st">  </span><span class="kw">annotation_custom</span>(</a>
<a class="sourceLine" id="cb4-5" data-line-number="5">    <span class="dt">grob =</span> g,</a>
<a class="sourceLine" id="cb4-6" data-line-number="6">    <span class="dt">xmin =</span> <span class="dv">1</span>,</a>
<a class="sourceLine" id="cb4-7" data-line-number="7">    <span class="dt">xmax =</span> <span class="dv">5</span>,</a>
<a class="sourceLine" id="cb4-8" data-line-number="8">    <span class="dt">ymin =</span> <span class="dv">5</span>,</a>
<a class="sourceLine" id="cb4-9" data-line-number="9">    <span class="dt">ymax =</span> <span class="dv">10</span></a>
<a class="sourceLine" id="cb4-10" data-line-number="10">  ) <span class="op">+</span></a>
<a class="sourceLine" id="cb4-11" data-line-number="11"><span class="st">  </span><span class="kw">annotation_custom</span>(</a>
<a class="sourceLine" id="cb4-12" data-line-number="12">    <span class="dt">grob =</span> <span class="kw">rectGrob</span>(<span class="dt">gp =</span> <span class="kw">gpar</span>(<span class="dt">fill =</span> <span class="st">&quot;white&quot;</span>)),</a>
<a class="sourceLine" id="cb4-13" data-line-number="13">    <span class="dt">xmin =</span> <span class="fl">7.5</span>,</a>
<a class="sourceLine" id="cb4-14" data-line-number="14">    <span class="dt">xmax =</span> <span class="ot">Inf</span>,</a>
<a class="sourceLine" id="cb4-15" data-line-number="15">    <span class="dt">ymin =</span> <span class="op">-</span><span class="ot">Inf</span>,</a>
<a class="sourceLine" id="cb4-16" data-line-number="16">    <span class="dt">ymax =</span> <span class="dv">5</span></a>
<a class="sourceLine" id="cb4-17" data-line-number="17">  )</a></code></pre></div>
<div class="figure">
<img src="" alt="Plot inset." />
<p class="caption">Plot inset.</p>
</div>
<p>In the second annotation, we used the convenient shorthand <code>+/-Inf</code> to signify the edge of the plot, irrespective of the data range.</p>
<p>An alternative way to place custom annotations within the plots is to use raw grid commands, which we will present at the end of this document. However, note that an advantage of using <code>annotation_custom</code> is that the inset plot is embedded in the main plot, therefore the whole layout can be saved with <code>ggsave()</code>, which will not be the case for plot modifications at the <code>grid</code> level.</p>
</div>
<div id="aligning-plot-panels" class="section level3">
<h3>Aligning plot panels</h3>
<p>A common request for presenting multiple plots on a single page is to align the plot panels. Often, <em>facetting</em> the plot solves this issue, with a flexible syntax, and in the true spirit of the Grammar of Graphics that inspired the ggplot2 design. However, in some situations, the various plot panels cannot easily be combined in a unique plot; for instance when using different geoms, or different colour scales.</p>
<p><code>grid.arrange()</code> makes no attempt at aligning the plot panels; instead, it merely places the objects into a rectangular grid, where they fit each cell according to the varying size of plot elements. The following figure illustrates the typical structure of ggplots.</p>
<div class="figure">
<img src="" alt="Colour-coded structure of examplar ggplot layouts. Note how the panels (red) vary in size from plot to plot, as they accommodate the other graphical components." />
<p class="caption">Colour-coded structure of examplar ggplot layouts. Note how the panels (red) vary in size from plot to plot, as they accommodate the other graphical components.</p>
</div>
<p>As we can readily appreciate, each plot panel stretches or shrinks according to the other plot elements, e.g. guides, axes, titles, etc. This often results in misaligned plot panels.</p>
<p>In this situation, instead of using <code>grid.arrange()</code>, we recommend to switch to the more powerful <code>gtable</code> package. In particular, the <code>rbind()</code>, <code>cbind()</code>, and <code>join</code> functions can provide a better alignment. The plots must first be converted to grobs (more specifically, gtables), using the <code>ggplotGrob()</code> function. The second step is to <code>bind</code> the two gtables, using the sizes from the first object, then assigning them to the maximum. Finally, the resulting object, a gtable, can be displayed using <code>grid.draw()</code> (it is no longer a <code>ggplot</code>, so <code>print()</code> no longer renders it on a device).</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb5-1" data-line-number="1"><span class="kw">library</span>(gtable)</a>
<a class="sourceLine" id="cb5-2" data-line-number="2">g2 &lt;-<span class="st"> </span><span class="kw">ggplotGrob</span>(p2)</a>
<a class="sourceLine" id="cb5-3" data-line-number="3">g3 &lt;-<span class="st"> </span><span class="kw">ggplotGrob</span>(p3)</a>
<a class="sourceLine" id="cb5-4" data-line-number="4">g &lt;-<span class="st"> </span><span class="kw">rbind</span>(g2, g3, <span class="dt">size =</span> <span class="st">&quot;first&quot;</span>)</a>
<a class="sourceLine" id="cb5-5" data-line-number="5">g<span class="op">$</span>widths &lt;-<span class="st"> </span><span class="kw">unit.pmax</span>(g2<span class="op">$</span>widths, g3<span class="op">$</span>widths)</a>
<a class="sourceLine" id="cb5-6" data-line-number="6"><span class="kw">grid.newpage</span>()</a>
<a class="sourceLine" id="cb5-7" data-line-number="7"><span class="kw">grid.draw</span>(g)</a></code></pre></div>
<div class="figure">
<img src="" alt="Aligning plot panels. Note that the two y axes have different widths." />
<p class="caption">Aligning plot panels. Note that the two y axes have different widths.</p>
</div>
</div>
<div id="aligning-complex-plots" class="section level3">
<h3>Aligning complex plots</h3>
<p>One possible strategy, implemented in <code>egg</code> with the low-level <code>gtable_frame</code> and high-level <code>ggarrange</code> functions, is to take the following steps:</p>
<ul>
<li>decompose each plot into a 3x3 layout, where the central cell corresponds to the core panels, surrounded by axes, legends, etc.</li>
<li>set the core width and height to a fixed dimension</li>
<li>bind the individual 3x3 gtables</li>
</ul>
<p>Aligning plots is achieved simply as follows,</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb6-1" data-line-number="1">p1 &lt;-<span class="st"> </span><span class="kw">ggplot</span>(mtcars, <span class="kw">aes</span>(mpg, wt, <span class="dt">colour =</span> <span class="kw">factor</span>(cyl))) <span class="op">+</span></a>
<a class="sourceLine" id="cb6-2" data-line-number="2"><span class="st">  </span><span class="kw">geom_point</span>()<span class="op">+</span><span class="st"> </span><span class="kw">theme_article</span>() <span class="op">+</span><span class="st"> </span><span class="kw">theme</span>(<span class="dt">legend.position =</span> <span class="st">'top'</span>) </a>
<a class="sourceLine" id="cb6-3" data-line-number="3">p2 &lt;-<span class="st"> </span><span class="kw">ggplot</span>(mtcars, <span class="kw">aes</span>(mpg, wt, <span class="dt">colour =</span> <span class="kw">factor</span>(cyl))) <span class="op">+</span></a>
<a class="sourceLine" id="cb6-4" data-line-number="4"><span class="st">  </span><span class="kw">geom_point</span>() <span class="op">+</span><span class="st"> </span><span class="kw">facet_wrap</span>(<span class="op">~</span><span class="st"> </span>cyl, <span class="dt">ncol =</span> <span class="dv">2</span>, <span class="dt">scales =</span> <span class="st">&quot;free&quot;</span>) <span class="op">+</span></a>
<a class="sourceLine" id="cb6-5" data-line-number="5"><span class="st">  </span><span class="kw">guides</span>(<span class="dt">colour =</span> <span class="st">&quot;none&quot;</span>) <span class="op">+</span></a>
<a class="sourceLine" id="cb6-6" data-line-number="6"><span class="st">  </span><span class="kw">theme_article</span>()</a>
<a class="sourceLine" id="cb6-7" data-line-number="7">  </a>
<a class="sourceLine" id="cb6-8" data-line-number="8"><span class="kw">ggarrange</span>(p1, p2, <span class="dt">widths =</span> <span class="kw">c</span>(<span class="fl">1.5</span>,<span class="dv">2</span>))</a></code></pre></div>
<p><img src="" /><!-- --></p>
<p>where many parameters are common to the <code>grid.arrange()</code> function from <code>gridExtra</code>.</p>
</div>
<div id="multiple-pages" class="section level3">
<h3>Multiple pages?</h3>
<p>Plots produced by <code>ggplot2</code>, including those with facets, and those combined with <code>grid.arrange()</code>, are always displayed on a single page. Sometimes, however, there isn’t enough room to display all the information, and it becomes necessary to split the output on multiple pages. A convenient approach consists in storing all the plots in a list, and plotting subsets of them on subsequent pages. The <code>gridExtra</code> package can simplify this process with the helper function <code>marrangeGrob()</code>, sharing a common syntax with <code>grid.arrange()</code>, but outputting as many pages as required by the total number of plots and per-page layout.</p>
</div>
</div>
<div id="mixed-graphical-components" class="section level2">
<h2>Mixed graphical components</h2>
<div id="titles-and-subtitles" class="section level3">
<h3>Titles and subtitles</h3>
<p>Adding a global title and/or subtitle to a page with multiple plots is easy with <code>grid.arrange()</code>: use the <code>top</code>, <code>bottom</code>, <code>left</code>, or <code>right</code> parameters to pass either a text string, or a grob for finer control.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb7-1" data-line-number="1"><span class="kw">grid.arrange</span>(</a>
<a class="sourceLine" id="cb7-2" data-line-number="2">  p3,</a>
<a class="sourceLine" id="cb7-3" data-line-number="3">  p3,</a>
<a class="sourceLine" id="cb7-4" data-line-number="4">  p3,</a>
<a class="sourceLine" id="cb7-5" data-line-number="5">  <span class="dt">nrow =</span> <span class="dv">1</span>,</a>
<a class="sourceLine" id="cb7-6" data-line-number="6">  <span class="dt">top =</span> <span class="st">&quot;Title of the page&quot;</span>,</a>
<a class="sourceLine" id="cb7-7" data-line-number="7">  <span class="dt">bottom =</span> <span class="kw">textGrob</span>(</a>
<a class="sourceLine" id="cb7-8" data-line-number="8">    <span class="st">&quot;this footnote is right-justified&quot;</span>,</a>
<a class="sourceLine" id="cb7-9" data-line-number="9">    <span class="dt">gp =</span> <span class="kw">gpar</span>(<span class="dt">fontface =</span> <span class="dv">3</span>, <span class="dt">fontsize =</span> <span class="dv">9</span>),</a>
<a class="sourceLine" id="cb7-10" data-line-number="10">    <span class="dt">hjust =</span> <span class="dv">1</span>,</a>
<a class="sourceLine" id="cb7-11" data-line-number="11">    <span class="dt">x =</span> <span class="dv">1</span></a>
<a class="sourceLine" id="cb7-12" data-line-number="12">  )</a>
<a class="sourceLine" id="cb7-13" data-line-number="13">)</a></code></pre></div>
<p><img src="" /><!-- --></p>
<p>Recent versions of ggplot2 have added built-in options to add a subtitle and a caption; the two stategies are somewhat complementary (<code>grid.arrange</code> aligns elements with respect to the entire plot, whereas ggplot2 places them with respect to the plot panel area).</p>
</div>
<div id="legends" class="section level3">
<h3>Legends</h3>
<p>When arranging multiple plots, one may wish to share a legend between some of them (although in general this is a clear hint that facetting might be a better option). The procedure involves extracting the legend from one graph, creating a custom layout, and inserting the plots and legend in their corresponding cell.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb8-1" data-line-number="1">grid_arrange_shared_legend &lt;-</a>
<a class="sourceLine" id="cb8-2" data-line-number="2"><span class="st">  </span><span class="cf">function</span>(...,</a>
<a class="sourceLine" id="cb8-3" data-line-number="3">           <span class="dt">ncol =</span> <span class="kw">length</span>(<span class="kw">list</span>(...)),</a>
<a class="sourceLine" id="cb8-4" data-line-number="4">           <span class="dt">nrow =</span> <span class="dv">1</span>,</a>
<a class="sourceLine" id="cb8-5" data-line-number="5">           <span class="dt">position =</span> <span class="kw">c</span>(<span class="st">&quot;bottom&quot;</span>, <span class="st">&quot;right&quot;</span>)) {</a>
<a class="sourceLine" id="cb8-6" data-line-number="6">    </a>
<a class="sourceLine" id="cb8-7" data-line-number="7">    plots &lt;-<span class="st"> </span><span class="kw">list</span>(...)</a>
<a class="sourceLine" id="cb8-8" data-line-number="8">    position &lt;-<span class="st"> </span><span class="kw">match.arg</span>(position)</a>
<a class="sourceLine" id="cb8-9" data-line-number="9">    g &lt;-</a>
<a class="sourceLine" id="cb8-10" data-line-number="10"><span class="st">      </span><span class="kw">ggplotGrob</span>(plots[[<span class="dv">1</span>]] <span class="op">+</span><span class="st"> </span><span class="kw">theme</span>(<span class="dt">legend.position =</span> position))<span class="op">$</span>grobs</a>
<a class="sourceLine" id="cb8-11" data-line-number="11">    legend &lt;-<span class="st"> </span>g[[<span class="kw">which</span>(<span class="kw">sapply</span>(g, <span class="cf">function</span>(x)</a>
<a class="sourceLine" id="cb8-12" data-line-number="12">      x<span class="op">$</span>name) <span class="op">==</span><span class="st"> &quot;guide-box&quot;</span>)]]</a>
<a class="sourceLine" id="cb8-13" data-line-number="13">    lheight &lt;-<span class="st"> </span><span class="kw">sum</span>(legend<span class="op">$</span>height)</a>
<a class="sourceLine" id="cb8-14" data-line-number="14">    lwidth &lt;-<span class="st"> </span><span class="kw">sum</span>(legend<span class="op">$</span>width)</a>
<a class="sourceLine" id="cb8-15" data-line-number="15">    gl &lt;-<span class="st"> </span><span class="kw">lapply</span>(plots, <span class="cf">function</span>(x)</a>
<a class="sourceLine" id="cb8-16" data-line-number="16">      x <span class="op">+</span><span class="st"> </span><span class="kw">theme</span>(<span class="dt">legend.position =</span> <span class="st">&quot;none&quot;</span>))</a>
<a class="sourceLine" id="cb8-17" data-line-number="17">    gl &lt;-<span class="st"> </span><span class="kw">c</span>(gl, <span class="dt">ncol =</span> ncol, <span class="dt">nrow =</span> nrow)</a>
<a class="sourceLine" id="cb8-18" data-line-number="18">    </a>
<a class="sourceLine" id="cb8-19" data-line-number="19">    combined &lt;-<span class="st"> </span><span class="cf">switch</span>(</a>
<a class="sourceLine" id="cb8-20" data-line-number="20">      position,</a>
<a class="sourceLine" id="cb8-21" data-line-number="21">      <span class="st">&quot;bottom&quot;</span> =<span class="st"> </span><span class="kw">arrangeGrob</span>(</a>
<a class="sourceLine" id="cb8-22" data-line-number="22">        <span class="kw">do.call</span>(arrangeGrob, gl),</a>
<a class="sourceLine" id="cb8-23" data-line-number="23">        legend,</a>
<a class="sourceLine" id="cb8-24" data-line-number="24">        <span class="dt">ncol =</span> <span class="dv">1</span>,</a>
<a class="sourceLine" id="cb8-25" data-line-number="25">        <span class="dt">heights =</span> <span class="kw">unit.c</span>(<span class="kw">unit</span>(<span class="dv">1</span>, <span class="st">&quot;npc&quot;</span>) <span class="op">-</span><span class="st"> </span>lheight, lheight)</a>
<a class="sourceLine" id="cb8-26" data-line-number="26">      ),</a>
<a class="sourceLine" id="cb8-27" data-line-number="27">      <span class="st">&quot;right&quot;</span> =<span class="st"> </span><span class="kw">arrangeGrob</span>(</a>
<a class="sourceLine" id="cb8-28" data-line-number="28">        <span class="kw">do.call</span>(arrangeGrob, gl),</a>
<a class="sourceLine" id="cb8-29" data-line-number="29">        legend,</a>
<a class="sourceLine" id="cb8-30" data-line-number="30">        <span class="dt">ncol =</span> <span class="dv">2</span>,</a>
<a class="sourceLine" id="cb8-31" data-line-number="31">        <span class="dt">widths =</span> <span class="kw">unit.c</span>(<span class="kw">unit</span>(<span class="dv">1</span>, <span class="st">&quot;npc&quot;</span>) <span class="op">-</span><span class="st"> </span>lwidth, lwidth)</a>
<a class="sourceLine" id="cb8-32" data-line-number="32">      )</a>
<a class="sourceLine" id="cb8-33" data-line-number="33">    )</a>
<a class="sourceLine" id="cb8-34" data-line-number="34">    </a>
<a class="sourceLine" id="cb8-35" data-line-number="35">    <span class="kw">grid.newpage</span>()</a>
<a class="sourceLine" id="cb8-36" data-line-number="36">    <span class="kw">grid.draw</span>(combined)</a>
<a class="sourceLine" id="cb8-37" data-line-number="37">    </a>
<a class="sourceLine" id="cb8-38" data-line-number="38">    <span class="co"># return gtable invisibly</span></a>
<a class="sourceLine" id="cb8-39" data-line-number="39">    <span class="kw">invisible</span>(combined)</a>
<a class="sourceLine" id="cb8-40" data-line-number="40">    </a>
<a class="sourceLine" id="cb8-41" data-line-number="41">  }</a>
<a class="sourceLine" id="cb8-42" data-line-number="42"></a>
<a class="sourceLine" id="cb8-43" data-line-number="43"><span class="kw">grid_arrange_shared_legend</span>(p1, p2)</a></code></pre></div>
<p><img src="" /><!-- --></p>
</div>
<div id="tables-and-other-grobs" class="section level3">
<h3>Tables and other grobs</h3>
<p>As we’ve seen in the previous examples, <code>ggplots</code> are grobs, which can be placed and manipulated. Likewise, other grobs can be added to the mix. For instance, one may wish to add a small table next to the plot, as produced by the <code>tableGrob</code> function in <code>gridExtra</code>.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb9-1" data-line-number="1"><span class="kw">grid.arrange</span>(</a>
<a class="sourceLine" id="cb9-2" data-line-number="2">  <span class="kw">tableGrob</span>(mtcars[<span class="dv">1</span><span class="op">:</span><span class="dv">4</span>, <span class="dv">1</span><span class="op">:</span><span class="dv">4</span>]),</a>
<a class="sourceLine" id="cb9-3" data-line-number="3">  p2,</a>
<a class="sourceLine" id="cb9-4" data-line-number="4">  <span class="dt">ncol =</span> <span class="dv">2</span>,</a>
<a class="sourceLine" id="cb9-5" data-line-number="5">  <span class="dt">widths =</span> <span class="kw">c</span>(<span class="fl">1.5</span>, <span class="dv">1</span>),</a>
<a class="sourceLine" id="cb9-6" data-line-number="6">  <span class="dt">clip =</span> <span class="ot">FALSE</span></a>
<a class="sourceLine" id="cb9-7" data-line-number="7">)</a></code></pre></div>
<p><img src="" /><!-- --></p>
</div>
</div>
<div id="alternative-options" class="section level2">
<h2>Alternative options</h2>
<p>We’ve focused on <code>grid.arrange()</code> and <code>ggarrange</code> for simplicity, but there are numerous alternatives to achieve similar arrangements of plots (all of which ultimately based on <code>grid</code>). We list below a few alternatives, in chronological order.</p>
<table>
<thead>
<tr class="header">
<th>Package</th>
<th align="center">Function(s)</th>
<th align="center">ggsave compat.</th>
<th align="center">alignment</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>grid</td>
<td align="center"><code>viewport</code>, <code>grid.layout</code></td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr class="even">
<td><a href="https://CRAN.R-project.org/package=gridExtra">gridExtra</a></td>
<td align="center"><code>grid.arrange</code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd">
<td><a href="http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2)">(r cookbook)</a></td>
<td align="center"><code>multiplot</code></td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr class="even">
<td><a href="https://CRAN.R-project.org/package=gtable">gtable</a></td>
<td align="center"><code>rbind</code>, <code>cbind</code></td>
<td align="center">yes</td>
<td align="center">yes</td>
</tr>
<tr class="odd">
<td><a href="https://CRAN.R-project.org/package=cowplot">cowplot</a></td>
<td align="center"><code>plot_grid</code></td>
<td align="center">yes*</td>
<td align="center">yes*</td>
</tr>
<tr class="even">
<td><a href="https://CRAN.R-project.org/package=multipanelfigure">multipanelfigure</a></td>
<td align="center"><code>multi_panel_figure</code></td>
<td align="center">yes</td>
<td align="center">yes</td>
</tr>
<tr class="odd">
<td><a href="https://CRAN.R-project.org/package=egg">egg</a></td>
<td align="center"><code>ggarrange</code></td>
<td align="center">yes</td>
<td align="center">yes</td>
</tr>
<tr class="even">
<td><a href="https://github.com/thomasp85/patchwork">patchwork</a></td>
<td align="center"><code>plot_layout</code></td>
<td align="center">yes</td>
<td align="center">yes</td>
</tr>
</tbody>
</table>
<div id="grid-viewports-and-layouts" class="section level3">
<h3>grid viewports and layouts</h3>
<p>Underlying all these other packages is the <code>grid</code> package, included in the core R distribution. This package provides the low-level functions used for drawing and placing objects on a device.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode r"><code class="sourceCode r"><a class="sourceLine" id="cb10-1" data-line-number="1"><span class="kw">pushViewport</span>(<span class="kw">viewport</span>(<span class="dt">layout =</span> <span class="kw">grid.layout</span>(<span class="dv">2</span>, <span class="dv">2</span>)))</a>
<a class="sourceLine" id="cb10-2" data-line-number="2">vplayout &lt;-<span class="st"> </span><span class="cf">function</span>(x, y) <span class="kw">viewport</span>(<span class="dt">layout.pos.row =</span> x, <span class="dt">layout.pos.col =</span> y)</a>
<a class="sourceLine" id="cb10-3" data-line-number="3"><span class="kw">print</span>(p1, <span class="dt">vp =</span> <span class="kw">vplayout</span>(<span class="dv">1</span>, <span class="dv">1</span><span class="op">:</span><span class="dv">2</span>))</a>
<a class="sourceLine" id="cb10-4" data-line-number="4"><span class="kw">print</span>(p2, <span class="dt">vp =</span> <span class="kw">vplayout</span>(<span class="dv">2</span>, <span class="dv">1</span>))</a>
<a class="sourceLine" id="cb10-5" data-line-number="5"><span class="kw">print</span>(p3, <span class="dt">vp =</span> <span class="kw">vplayout</span>(<span class="dv">2</span>, <span class="dv">2</span>))</a></code></pre></div>
<p><img src="" /><!-- --></p>
</div>
</div>
<div id="acknowledgements" class="section level2">
<h2>Acknowledgements</h2>
<p>Parts of this document were <a href="https://github.com/tidyverse/ggplot2/issues/1239">originally written by Hadley Wickham as a draft vignette</a> for the <code>ggplot2</code> package; the contents have since been shuffled around quite a bit and I have lost track of the exact history of edits.</p>
</div>



<!-- dynamically load mathjax for compatibility with self-contained -->
<script>
  (function () {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src  = "https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML";
    document.getElementsByTagName("head")[0].appendChild(script);
  })();
</script>

</body>
</html>
